<template>
  <el-form ref="form" :model="spu" label-width="80px">
    <el-form-item label="SPU名称"
      ><el-input
        placeholder="SPU名称"
        style="width: 200px"
        v-model="spu.spuName"
      ></el-input
    ></el-form-item>
    <el-form-item label="品牌">
      <el-select v-model="spu.tmId" placeholder="请选择品牌">
        <el-option
          v-for="(tm, index) in spuTradeMarkList"
          :key="tm.id"
          :label="tm.tmName"
          :value="tm.id"
        >
        </el-option>
      </el-select>
    </el-form-item>
    <el-form-item label="SPU描述"
      ><el-input
        placeholder="SPU描述"
        :rows="4"
        type="textarea"
        v-model="spu.description"
      ></el-input
    ></el-form-item>
    <el-form-item label="SPU图片"
      ><el-upload
        action="list-api/admin/product/upload"
        :file-list="spuPictureCard"
        list-type="picture-card"
        :on-preview="handlePictureCardPreview"
        :on-remove="handleRemove"
        :on-success="handleAvatarSuccess"
        :before-upload="beforeAvatarUpload"
      >
        <i class="el-icon-plus"></i>
      </el-upload>
      <el-dialog :visible.sync="dialogVisible">
        <img width="100%" :src="dialogImageUrl" alt="" /> </el-dialog
    ></el-form-item>
    <el-form-item label="销售属性">
      <el-select
        v-model="unSaleAttrName"
        :placeholder="`还有${unSelectSaleAttr.length}未选择`"
      >
        <el-option
          v-for="(unSaleAttr, index) in unSelectSaleAttr"
          :key="unSaleAttr.id"
          :label="unSaleAttr.name"
          :value="unSaleAttr.id"
        >
        </el-option>
      </el-select>
      <el-button
        type="primary"
        icon="el-icon-plus"
        @click="addSaleAttrName(unSaleAttrName)"
        :disabled="!unSaleAttrName"
        >添加销售属性</el-button
      >
      <el-table
        :data="spuSaleAttrList"
        border
        style="width: 100%; margin-top: 20px"
      >
        <el-table-column type="index" label="序号" width="180" align="center">
        </el-table-column>
        <el-table-column
          prop="saleAttrName"
          label="属性名"
          width="180"
          align="center"
        >
        </el-table-column>
        <el-table-column
          prop="spuSaleAttrList"
          label="属性名称列表"
          width="width"
        >
          <template slot-scope="{ row, $index }">
            <el-tag
              :key="spuSaleAttrValue.id"
              v-for="(spuSaleAttrValue, index) in row.spuSaleAttrValueList"
              closable
              :disable-transitions="false"
              @close="handleClose(spuSaleAttrValue.id, $index)"
            >
              {{ spuSaleAttrValue.saleAttrValueName }}
            </el-tag>
            <el-input
              class="input-new-tag"
              v-if="row.flag"
              v-model="inputValue"
              :ref="$index"
              size="small"
              @keydown.native.enter="handleInputConfirm($index, 'enter')"
              @blur="handleInputConfirm($index)"
            >
            </el-input>
            <el-button
              v-else
              class="button-new-tag"
              size="small"
              @click="showInput($index)"
              >添加</el-button
            >
          </template>
        </el-table-column>
      </el-table>
    </el-form-item>
    <el-form-item
      ><el-button type="primary" @click="addSpu">保存</el-button
      ><el-button @click="cancelSpu">取消</el-button></el-form-item
    >
  </el-form>
</template>

<script>
export default {
  name: 'SpuForm',
  data() {
    return {
      spu: {
        category3Id: '', // 三级分类 id
        description: '', // spu描述
        id: '', // spuId 修改需要，新增不需要
        spuImageList: [], // 图片地址
        spuName: '',
        spuSaleAttrList: [],
        tmId: ''
      },
      spuImageList: [], // 图片地址
      spuSaleAttrList: [],
      spuTradeMarkList: [],
      spuSaleAttrValueList: [], // 品牌属性值名称
      inputVisible: false, // 控制品牌属性值名称的input隐藏
      inputValue: '', // input的品牌属性值名称
      baseSaleAttrList: [], // 销售品牌
      unSaleAttrName: '', // 未选择的销售品牌
      enterFlag: false, // 使用回车确认的表示
      dialogImageUrl: '', // 图片路径
      dialogVisible: false, // 查看放大图片弹窗
      spuPictureCard: [] // 图片墙数组
    }
  },
  methods: {
    // 父组件调用 获取spu需要展示的数据
    async getSpuProperty(category3Id, spuid) {
      this.spu.category3Id = category3Id
      if (spuid) {
        // 有id为修改页面
        const result = await this.$api.spu.reqGetSpuProperty(spuid)
        if (result.code === 200) {
          this.spu = result.data
        }
        this.initData()
      } else {
        // 无id为新增页面
        this.init()
      }
    },
    // 添加和修改spu都需要初始化的数据
    async init() {
      // 初始化销售品牌的数据
      const resultSaleAttr = await this.$api.spu.reqGetBaseSaleAttrList()
      if (resultSaleAttr.code === 200) {
        this.baseSaleAttrList = resultSaleAttr.data
      }
      // 获取品牌数据
      const result = await this.$api.spu.reqGetTrademarkList()
      if (result.code === 200) {
        this.spuTradeMarkList = result.data
      }
    },
    // 初始化spu需要的数据
    async initData() {
      this.init()
      // 初始化品牌属性
      this.spuSaleAttrList = this.spu.spuSaleAttrList
      // 初始化品牌属性值名称  先置空数组
      this.spuSaleAttrValueList = []
      this.spuSaleAttrList.forEach((element) => {
        // 添加input是否隐藏表示 flag
        this.$set(element, 'flag', false)
        this.spuSaleAttrValueList.push(element.spuSaleAttrValueList)
      })
      // 初始化图片
      const resultImgList = await this.$api.spu.reqGetSpuImageLIst(this.spu.id)
      if (resultImgList.code === 200) {
        // 整理数据给照片墙显示
        this.spuPictureCard = []
        resultImgList.data.forEach((item) => {
          this.spuPictureCard.push({ name: item.imgName, url: item.imgUrl })
        })
      }
    },
    // 销售属性里的属性名称列表添加按钮的回调
    showInput(index) {
      this.spuSaleAttrList[index].flag = !this.spuSaleAttrList[index].flag
      // 获取输入框焦点
      this.$nextTick(() => {
        this.$refs[index].focus()
      })
    },
    // 销售属性里的属性名称列表input改变的回调
    handleInputConfirm(index, enter) {
      // 防止使用回车键确认时，二次出发函数
      if (this.enterFlag) {
        this.enterFlag = false
        return
      }
      // 回车键确认时，再次出发blur，进入此函数，在前面直接返回
      if (enter === 'enter') {
        this.enterFlag = true
      }
      if (this.inputValue.trim() === '') {
        // 保存input里的值
        this.$message.warning('输入正确的属性值')
        this.$refs[index].focus()
        return
      }
      const inputValue = this.inputValue.trim()
      // 排重
      const result = this.spuSaleAttrValueList[index].some((item) => {
        return item.saleAttrValueName === inputValue
      })
      if (result) {
        this.$message.warning('输入的属性值重复')
        this.$refs[index].focus()
        return
      }
      // 隐藏input
      this.spuSaleAttrList[index].flag = false
      if (inputValue) {
        // 从spuSaleAttrList数组中收集，防止undefined
        const obj = {
          // TODO: baseSaleAttrId   不清楚是否需要收集，先收集
          baseSaleAttrId: this.spuSaleAttrList[index].baseSaleAttrId,
          saleAttrName: this.spuSaleAttrList[index].saleAttrName,
          saleAttrValueName: inputValue,
          spuId: this.spu.id
        }
        this.spuSaleAttrList[index].spuSaleAttrValueList.push(obj)
        // this.spuSaleAttrValueList[index].push(obj)
      }
      // 置空input输入的内容
      this.inputValue = ''
    },
    // 删除spu里的销售属性的属性名称
    handleClose(id, index) {
      this.spuSaleAttrValueList[index].splice(
        this.spuSaleAttrValueList[index].indexOf(id),
        1
      )
    },
    // 添加销售属性
    addSaleAttrName(saleAttrName) {
      const saleAttr = this.baseSaleAttrList.find((item) => {
        return item.id === saleAttrName
      })
      const obj = {
        baseSaleAttrId: saleAttr.id,
        saleAttrName: saleAttr.name,
        flag: false,
        spuId: this.spu.id,
        spuSaleAttrValueList: []
      }
      // 添加新销售属性后，spuSaleAttrValueList也要新增一个数组，在handleInputConfirm函数里使用
      this.spuSaleAttrValueList.push([])
      this.spuSaleAttrList.push(obj)
      // 清空销售属性里数据
      this.unSaleAttrName = ''
    },
    // 图片删除回调
    handleRemove(file, fileList) {
      this.spuImageList = fileList
      this.spuPictureCard = fileList
    },
    // 查看图片回调
    handlePictureCardPreview(file) {
      this.dialogImageUrl = file.url
      this.dialogVisible = true
    },
    // 图片上传成功的回调
    handleAvatarSuccess(res, file, fileList) {
      this.spuImageList = fileList
      this.spuPictureCard = fileList
    },
    // 图片上传前的逻辑
    beforeAvatarUpload(file) {
      const isJPG = file.type === 'image/jpeg'
      const isLt2M = file.size / 1024 / 1024 < 2

      if (!isJPG) {
        this.$message.error('上传头像图片只能是 JPG 格式!')
      }
      if (!isLt2M) {
        this.$message.error('上传头像图片大小不能超过 2MB!')
      }
      return isJPG && isLt2M
    },
    // 保存spu
    async addSpu() {
      // 收集数据
      // 整理图片数据 id: 0,imgName:"string",imgUrl:"string",spuId: 0
      this.spu.spuImageList = this.spuPictureCard.map((item) => {
        return {
          imgName: item.name,
          imgUrl: item.response ? item.response.data : item.url
        }
      })
      this.spuSaleAttrList.forEach((item) => {
        delete item.flag
      })
      this.spu.spuSaleAttrList = this.spuSaleAttrList
      console.log(this.spu)
      // 发请求
      const result = await this.$api.spu.reqAddOrUpdateSpuInfo(this.spu)
      if (result.code === 200) {
        this.$message.success('spu保存成功')
        // 切回主页面
        this.$emit('changeScene', 1)
        // 清空数据
        // Object.assign:es6中新增的方法可以合并对象
        // 组件实例this._data,可以操作data当中响应式数据
        // this.$options可以获取配置对象，配置对象的data函数执行，返回的响应式数据为空的
        Object.assign(this._data, this.$options.data())
      }
    },
    // 取消
    cancelSpu() {
      Object.assign(this._data, this.$options.data())
      // 切回主页面
      this.$emit('changeScene', 1)
    }
  },
  computed: {
    // 过滤已经有的销售品牌，展示未添加的销售品牌
    unSelectSaleAttr() {
      // 整个平台的销售属性一共三个：尺寸、颜色、版本 ----saleAttrList
      // 当前SPU拥有的属于自己的销售属性SPU.spuSaleAttrList  ----颜色
      // 数组的过滤方法，可以从已有的数组当中过滤出用户需要的元素，并未返回一个新的数据
      const result = this.baseSaleAttrList.filter((saleAttr) => {
        return this.spu.spuSaleAttrList.every((value) => {
          return saleAttr.name !== value.saleAttrName
        })
      })
      return result
    }
  }
}
</script>

<style>
.el-tag + .el-tag {
  margin-left: 10px;
}
.button-new-tag {
  margin-left: 10px;
  height: 32px;
  line-height: 30px;
  padding-top: 0;
  padding-bottom: 0;
}
.input-new-tag {
  width: 90px;
  margin-left: 10px;
  vertical-align: bottom;
}
</style>